home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / spin3d.lzh / SPIN6.C < prev    next >
C/C++ Source or Header  |  1994-03-29  |  10KB  |  316 lines

  1. /*   *** SPIN6.C ***
  2.      ***************
  3.      Will spin ==========>  A triangle in 3 space <===============
  4.              
  5.      This uses the code from SPIN4.c PLUS it implements 
  6.      PERSPECTIVE VIEWING.
  7.  
  8.      It also switches from 60 to 50Hz (for the monitor), then 
  9.      switched back to 60Hz after you quit. This helps the speed somewhat.
  10.     
  11.      Perspective Viewing 
  12.      -------------------
  13.      Lets assume a righ-handed coord system, with horizontal 
  14.      screen the x axis, vertical screen the Y axis and the positive
  15.      z axis sticking out of the screen.
  16.  
  17.      In all the other programs,we have been using what is called
  18.      PARALLEL projections, you can't tell depth from them. To be 
  19.      exact, we have been using Orthographic projections(a subset of 
  20.      Parallel projections) All we had to do is drop the z coord
  21.      to project onto the xy axis, or drop the x coord to project
  22.      onto the yz axis, etc. 
  23.  
  24.      But what if we want more realism?? We use Perspective projections of course!
  25.      The basic idea behind it that if a point has a small z coordinate value, it is 
  26.      further away from the viewer, and hence smaller. This gives the illusion of 'depth'
  27.      
  28.       To do this we could just divide x and y by the z value, but this gives a rather
  29.       strange effect. You will notice that the CRT(screen) is some distance 'd' away from
  30.       your eyes, we need to take this into account.
  31.  
  32.       Let 'pdist' = distance from your eyes to the screen(in pixels) a good value is around 200
  33.        
  34.       Then the equations we need are:
  35.  
  36.             x' = (x / (z+pdist)) * pdist
  37.             y' = (y / (z+pdist)) * pdist
  38.      
  39.          z + pdist moves your view(eye) away from the middle of the object
  40.          to a distance 'pdist' away from it.
  41.  
  42.  
  43.                  So lets try this out!!
  44.  
  45.                        March 28 ,1994  jeff bilger 
  46.                          jbilger@cs.tamu.edu
  47.  
  48. */
  49.  
  50.                         /* define our perspective stuff */
  51. float pdist= 200.;
  52.  
  53. #define perx(p) \
  54.         (perspective ? ((p.x/(p.z+pdist))*pdist):p.x)
  55. #define pery(p) \
  56.         (perspective ? ((p.y/(p.z+pdist))*pdist):p.y)
  57.  
  58.  
  59.  
  60. #include <math.h>
  61. #include <linea.h>
  62. #include <osbind.h>
  63. int pts[4][2] = { 
  64.     320, 050,
  65.     120, 150,
  66.     520, 150,
  67.     320, 050
  68. };
  69. lineaport *theport;
  70.  
  71. long mu_global_s();                     /* prototype, tells our 
  72.                                           Assembly language function
  73.                                            to return a long int  */
  74. long mu_global_c();  /* multiply 32 bit global w/ a precomputed sin or cos value */
  75.  
  76.  
  77. #define SCALE 2048L       /* so far 2048 is the upper bounds scale
  78.                               i can get W/O overflow */
  79. #define BITSH 11        /* what to shift (ie DIVIDE) by. this number
  80.                            2^11 = 2048 */
  81.  
  82.  
  83. typedef struct {long x,y,z;} point3d;   /* our faithful structure that defines a point in 3 space*/
  84.  
  85.           
  86. /* these are used to allocate size of arrays */
  87. #define NPTS   25                 /* max allowable points */
  88. #define NLINES 50                
  89. #define NFACES 50                
  90.  
  91.  
  92. #define I ( SCALE  )           /* set up a SCALE factor */
  93.  
  94. point3d point_[NPTS] =         /* define our triangle in 3d */
  95.         { 
  96.           I,I,I,     3*I,I,I, 2*I,I,-I,  2*I,-I,I/2,
  97.  },
  98.         drawpt1[NPTS],drawpt2[NPTS];     /* for fast draw/erasing look up */
  99.  
  100.  
  101.  
  102. int 
  103.     npts  = 4,         /* linefrom, lineto for drawing lines */                                                                                            
  104.     linefrom[NLINES] = {0,1,2,0,1,2},     /* set up lines to draw */
  105.     lineto[NLINES]   = {1,2,0,3,3,3}, 
  106.     nlines = 6,         /* number of lines */
  107.     x_offset=320,       /* for viewport mapping */
  108.     y_offset=100,
  109.     z_offset=1;
  110.  
  111. long cos_2=2048;    /* cos of 3 degrees * scale of 2048 */
  112. long sin_2=107;     /* sin of 3 degrees * scale of 2048 */
  113.  
  114.  
  115. extern palmode();        /* routine to torn on PAL mode (50Hz) */
  116. char *ptr;
  117. extern ntscmode();       /* routine to turn off PAL mode and go back
  118.                             to NTSC mode (60Hz) */ 
  119.  
  120. main()
  121. {
  122. register int i,j;   /* use em for FOR loops */
  123. point3d pointi;     /* declare one instance of our point3d struct */
  124. int color =1;       /* color to draw triangle */
  125. char com;           /* for user input */
  126.  
  127.  
  128. Supexec( palmode );
  129.  
  130. puts("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
  131. puts("1-Spin Y  2-Spin X  3-Spin Z  9-Quit\n");
  132.  
  133. theport = a_init();                   /* line a invokage */    
  134.     theport -> plane0 = 1;
  135.     theport -> plane1 = 0;
  136.     theport -> plane2 = 0;
  137.     theport -> plane3 = 0;
  138.  
  139.  
  140.    
  141. for(i=0;i<nlines;i++)  /* set up points-to-connect lookup table*/
  142. { drawpt1[i] = point_[linefrom[i]];
  143.   drawpt2[i] = point_[lineto[i]];  
  144. }
  145.  
  146. com = 0x32;                       /* set to spin about x */
  147.  
  148. while( com != 0x39 )
  149. {
  150. if( Bconstat(2) )       /* if keypress */
  151.  com = Bconin(2);       /* get input */
  152.  
  153.  
  154.                                   /* The main loop */
  155.  for(i=0;i<npts;i++)
  156.    {
  157.    pointi = point_[i];        /* get current point data. We do this for efficiency, since we will use this value many times within one loop
  158.                                  it's more efficient to compute it's value only once */
  159.    
  160.     if(com == 0x31) {              /* spin y */
  161.                point_[i].x =( mu_global_c(pointi.x)  -
  162.                               mu_global_s(pointi.z))>>BITSH; /* since our points are scaled AND or trig angles, sin&cos values are scaled we must divide by scale once here*/
  163.                point_[i].z =( mu_global_s(pointi.x) +
  164.                               mu_global_c(pointi.z))>>BITSH;
  165.  
  166.                     }
  167.     if(com == 0x32) {              /* spin x */
  168.                 point_[i].y =( mu_global_c(pointi.y)  +
  169.                                mu_global_s(pointi.z))>>BITSH;
  170.                 point_[i].z =( -(mu_global_s(pointi.y)) +
  171.                                  mu_global_c(pointi.z))>>BITSH;
  172.                     }
  173.     if(com == 0x33) {              /* spin z */
  174.                 point_[i].x =( mu_global_c(pointi.x)  +
  175.                                mu_global_s(pointi.y))>>BITSH;
  176.                 point_[i].y =( mu_global_c(pointi.y)  -
  177.                                mu_global_s(pointi.x))>>BITSH;
  178.                     }
  179.   
  180.  
  181.    }
  182.  
  183.                               /* draw and erase triangle */
  184.   for(i=0;i<nlines;i++)
  185.    { draw3dline(drawpt1[i],drawpt2[i],0);  /*erase */
  186.      draw3dline(drawpt1[i]=point_[linefrom[i]],drawpt2[i]=point_[lineto[i]],color);
  187.      /* draw it */
  188.   }
  189.    
  190.  
  191. }/* end of while */
  192.  
  193.  
  194. Supexec( ntscmode );
  195.  
  196. } /* end of main */
  197.  
  198.  
  199. /**************/
  200. palmode()
  201. {
  202.  
  203. ptr = (char *)0x448;
  204. *ptr = 1;
  205. }
  206. /**************/        /* redundant....I know */
  207. ntscmode()
  208. {
  209.  
  210. ptr = (char *)0x448;
  211. *ptr = 0;
  212. }
  213.  
  214. /*******************************/
  215.  
  216. draw3dline(p1,p2,color)
  217. point3d p1,p2;
  218. int color;
  219. {
  220.  int x1,y1,x2,y2,z1,z2;
  221.   
  222.  
  223.  x1 = p1.x >>BITSH-5;        /* scale down the coords */
  224.  y1 = p1.y >>BITSH-5;
  225.  x2 = p2.x >>BITSH-5;
  226.  y2 = p2.y >>BITSH-5;
  227.  z1 = p1.z >>BITSH-5;
  228.  z2 = p2.z >>BITSH-5;
  229.  
  230.  
  231.  /* project onto the xy plane */
  232.  
  233.             /* compute the perspective view */
  234.  x1 = (float)((x1/(z1+pdist)) * pdist);
  235.  y1 = (float)((y1/(z1+pdist)) * pdist);
  236.  x2 = (float)((x2/(z2+pdist)) * pdist);
  237.  y2 = (float)((y2/(z2+pdist)) * pdist);
  238.  
  239.  
  240. /* add viewport transformation */
  241. x1 +=x_offset;
  242. y1 +=y_offset;
  243. x2 +=x_offset;
  244. y2 +=y_offset; 
  245.  
  246. theport -> plane0 = color;
  247.  
  248.  
  249. a_line(x1,y1,x2,y2);
  250.  
  251. }
  252.  
  253.  
  254.  
  255. /***************************************************************/
  256. /* We will now modify the assembly mult. routine to be as efficient
  257.    as possible. We will make 2 mult. routines, one to multiply 
  258.    by a precomputed SINE value, and one to multiply by a precomputed
  259.    COSINE value
  260.    ************************************************************/
  261.  
  262. /*******************************************************/
  263. /* Multiply 1 16 bit(GLOBAL) SIGNED number b by a precomputed 
  264.    SINE value of 3 degrees (then the sine value was * SCALE where
  265.    scale was 2048 )
  266.  
  267.   and return the 32 bit resul